;;############################################################################
;; bargraph.lsp
;; Copyright (c) 1998-9 by Forrest W. Young
;; Code to implement bar graph and stacked bar graph object prototypes.
;; Includes one of the two prototype objects in ViSta:
;; bar-graph,  based on the Young-Kwan mosaic algorithm: stacked/side-by-side
;; The other is in the histfrq3.lsp file. It is:
;; bar-graph2, based on the deLeeuw-Bond histofreq algorithm: side-by-side

;;############################################################################
        
;;############################################################################
;; stacked bar graph object prototype (inherits from mosaic plot)
;;############################################################################


 #|THIS IS THE OLD CONSTRUCTOR FUNCTION 
   IT IS REPLACED BY CODE IN PLOTS003.LSP BY FWY DEC 2002

(defun bar-graph 
  (cells levels &key (standardize t) stacked color-values
         way-labels level-labels freq freqs (connect t)
         (legend (send current-object :name))
         (title "Bar Graph") (show t) (size '(250 250)) (location '(50 50)) )
"Creates a side-by-side frequency or probability bar graph of 1- to 4-way data, or stacked bar graph for 2- or 3-way data using the Young-Kwan mosaic algorithm.
Args: CELLS LEVELS &KEY FREQ STACKED COLOR-VALUES (STANDARDIZE T) (CONNECT T) WAY-LABELS LEVEL-LABELS LEGEND TITLE (SHOW T) SIZE LOCATION
Arguments used as with MOSAIC PLOT.
CELLS is a list of cells in way-major order. 
LEVELS specifies number of levels for each way. 
FREQ specifies that the data are frequency data. 
STACKED specifies whether intial plot is stacked (when possible) or side-by-side.
COLOR-VALUES is a list in same order as CELLS, which is used to color cells according to the specified values (standardized when STANDARDIZE T).
CONNECT specifies whether bars are connected by rows."
  (if (or freq freqs) (setf freq t)) 
  #-msdos(warning-message "BarGraphs do not draw correctly for this preview release of ViSta 6 for the Mac (they work in ViSta for Windows.)")
  (send stacked-bar-graph-proto 
        :new cells levels :freq freq :connect connect
        :way-labels way-labels :level-labels level-labels
        :color-values color-values :standardize standardize 
        :stacked stacked :legend1 legend 
        :legend2 (if stacked "Stacked Bar Graph" "Bar Graph") 
        :title title :show show :size size :location location)
  )
|#

(defun bar-chart (&rest args)
"Alias for bar-graph"
  (apply #'bar-graph args))

(defun stacked-bar-graph (&rest args)
"Alias for bar-graph"
  (apply #'bar-graph args))

(defun stacked-bar-chart (&rest args)
"Alias for bar-graph"
  (apply #'bar-graph args))

(defproto stacked-bar-graph-proto 
  '(bar-cells bar-levels bar-colors bar-way-labels bar-level-labels 
      side-by-side prob color-key? connect) 
  () mosaic-proto)

(defmeth stacked-bar-graph-proto :bar-cells (&optional (list nil set))
"Args: (&optional list)
Sets or returns original bar-graph cell frequencies."
  (if set (setf (slot-value 'bar-cells) list))
  (slot-value 'bar-cells))

(defmeth stacked-bar-graph-proto :bar-levels (&optional (list nil set))
"Args: (&optional list)
Sets or returns original bar-graph levels."
  (if set (setf (slot-value 'bar-levels) list))
  (slot-value 'bar-levels))

(defmeth stacked-bar-graph-proto :bar-colors (&optional (list nil set))
"Args: (&optional list)
Sets or returns original bar-graph colors."
  (if set (setf (slot-value 'bar-colors) list))
  (slot-value 'bar-colors))

(defmeth stacked-bar-graph-proto :bar-level-labels  (&optional (list nil set))
"Args: (&optional list)
Sets or returns original bar-level-labels."
  (if set (setf (slot-value 'bar-level-labels ) list))
  (slot-value 'bar-level-labels ))

(defmeth stacked-bar-graph-proto :bar-way-labels (&optional (list nil set))
"Args: (&optional list)
Sets or returns original bar-way-labels."
  (if set (setf (slot-value 'bar-way-labels) list))
  (slot-value 'bar-way-labels))

(defmeth stacked-bar-graph-proto :side-by-side (&optional (logical nil set))
"Args: (&optional logical)
Sets or returns whether graph is side-by-side."
  (if set (setf (slot-value 'side-by-side) logical))
  (slot-value 'side-by-side))

(defmeth stacked-bar-graph-proto :prob (&optional (logical nil set))
"Args: (&optional logical)
Sets or returns whether graph shows probabilities or frequencies on y-axis."
  (if set (setf (slot-value 'prob) logical))
  (slot-value 'prob))

(defmeth stacked-bar-graph-proto :color-key? (&optional (logical nil set))
"Args: (&optional logical)
Sets or returns whether color spectrum should be shown."
  (if set (setf (slot-value 'color-key?) logical))
  (slot-value 'color-key?))

(defmeth stacked-bar-graph-proto :connect (&optional (logical nil set))
"Args: (&optional logical)
Sets or returns whether color spectrum should be shown."
  (if set (setf (slot-value 'connect) logical))
  (slot-value 'connect))

(defmeth stacked-bar-graph-proto :isnew 
  (cells levels &key way-labels level-labels stacked
         freq color-values standardize connect
         legend1 legend2 title show size location plot-button)
  ;new statement to generate default chi-sq based colors
  (when (not color-values)
        (setf color-values (combine (send self :chi-sq-contributions cells levels))))

  (when color-values (send self :color-key? t))
  (when (not color-values) (setf standardize nil))
  (when (and color-values standardize) 
        (setf color-values 
              (if (= (length (remove-duplicates color-values)) 1)
                  (repeat 0.0 (length color-values))
                  (standardize color-values))))
  (send self :bar-colors color-values)
  (when (or (= (length levels) 1)
            (and (> (length levels) 3) stacked))
        (setf stacked nil))
  (send self :bar-cells cells)
  (send self :bar-levels levels)
  (send self :bar-level-labels level-labels)
  (send self :bar-way-labels way-labels)
  (send self :side-by-side (not stacked))
  (send self :legend1 legend1)
  (send self :legend2 "Bar Graph")
  (send self :switch-plot-type)
  (let* ((side-by-side (not stacked))
         (result (send self :massage-data 
                      cells levels way-labels level-labels 
                      side-by-side color-values t))
         (mosaic-data (first result))
         (mosaic-levels (second result))
         (colors (third result))
         (waylabs (fourth result))
         (levlabs (fifth result))
         (nways (length levels))
         )
    (send self :fixed-aspect nil)
    (call-next-method mosaic-data mosaic-levels t nil colors
                      standardize nil plot-button
                      (list 20 0) waylabs levlabs 
                      legend1 legend2 title nil size location)
    (send self :connect connect)
    (when connect (send self :connection-type 1))
    (send self :bar t)
    (send self :fixed-aspect nil)
    (let ((overlay (first (send self :slot-value 'overlays)))
          (color-key? (send self :color-key?))
          (ways (send self :ways)))
;(send self :show-window)
      (when (= 1 ways) (setf nylines 0))
      (when  color-key? (send self :add-color-spectrum))
      (send self :fix-margins)
      (send self :showing-labels nil)
      (when side-by-side (send overlay :install-button ':new-y))
      (when (or (= (length levels) 1)(> (length levels) 3))
            (send overlay :remove-button ':new-x))
      (when (send self :connect)
            (send self :connection-type (if side-by-side 0 1)))
;(break)
      (when show (send self :show-window)))
    self))

(defmeth stacked-bar-graph-proto :new-plot 
  (cells levels  &key freq color-values
         (stacked (not (send self :side-by-side))) 
         way-labels level-labels show (standardize t))
"Generates a new plot.
Args: CELLS LEVELS &KEY FREQ COLOR-VALUES STACKED WAY-LABELS LEVEL-LABELS SHOW STANDARDIZE. See BAR-GRAPH for usage. Cannot use COLOR-VALUES here unless used in original BAR-GRAPH."
  (let* ((side-by-side (not stacked))
         (overlay (first (send self :slot-value 'overlays)))
         (plot-values nil)
         (gaps '(20 0))
         (send self :side-by-side side-by-side))
    (cond 
      ((or (= (length levels) 1)(> (length levels) 3))
       (setf stacked nil)
       (setf side-by-side t)
       (send overlay :remove-button ':new-x))
      (t (send overlay :install-button ':new-x)))
    (cond
      ((send self :bar)
       (when (and color-values standardize) 
             (setf color-values 
                   (if (= (length (remove-duplicates color-values)) 1)
                       (repeat 0.0 (length color-values))
                       (standardize color-values))))
       (send self :bar-colors color-values)
       (send self :bar-cells cells)
       (send self :bar-levels levels)
       (send self :bar-level-labels level-labels)
       (send self :bar-way-labels way-labels)
       (send self :side-by-side (not stacked))
       (send self :switch-plot-type)
       (let* ((result (send self :massage-data 
                            cells levels way-labels level-labels 
                            side-by-side color-values nil))
              (mosaic-data (first result))
              (mosaic-levels (second result))
              (colors (third result))
              (waylabs (fourth result))
              (levlabs (fifth result))
              )
         (send self :start-buffering)
         (call-next-method mosaic-data mosaic-levels :freq t :way-labels waylabs
                           :level-labels levlabs :color-values colors :gaps gaps
                           :standardize nil )
         (send self :buffer-to-screen)))
      (t ;do this when called from isnew only
         (call-next-method cells levels :freq t 
                           :color-values color-values :standardize nil
                           :gaps gaps :way-labels way-labels 
                           :level-labels level-labels :show show)))
    (when (send self :connect)
          (send self :connection-type (if side-by-side 0 1)))
    ))

(defmeth stacked-bar-graph-proto :fix-margins ()
  (let ((color-key? (send self :color-key?))
        (lh (+ (send self :text-ascent) (send self :text-descent) 2))
        (nxlines 2) 
        (nylines 2))
    (send self :setting-margins t)
    (send self :margin (- (* nylines lh) 36) 19 
          (if color-key? 0 -20) (- (* nxlines lh) 40))
    (send self :setting-margins nil)))

(defmeth stacked-bar-graph-proto :massage-data
  (cells levels way-labels level-labels side-by-side color-values initial)
  (let ((nways (length levels)) (array)
        (matrix) (nobs) (nvar) (col-sums) (invisible)
        (mosaic-data) (mosaic-levels) (colors color-values) 
        (levlabs) (result)
        (waylabs))  
    (when (and (not side-by-side) (= nways 3))
          (setf array (make-array levels :initial-contents cells))
          (setf cells (combine 
                 (mapcar #'(lambda (k)
                   (mapcar #'(lambda (i)
                     (combine 
                      (select array k (iseq (select levels 1)) i)))
                           (iseq (select levels 2))))
                         (iseq (select levels 0)))))
          
          (setf levels (list (* (elt levels 0) (elt levels 2)) (elt levels 1)))
          (setf way-labels (list (strcat (elt way-labels 0) "*" (elt way-labels 2))
                                 (elt way-labels 1)))
          (setf level-labels 
                (list (string-product (elt level-labels 2) (elt level-labels 0)
                                     :reverse t ) 
                      (elt level-labels 1)))
          (setf nways 2))
    (when (= nways 2) ; (and (not initial) (= nways 2))
          (setf cells (combine (transpose (matrix levels cells))))
          (setf levels (reverse levels))
          (setf way-labels (reverse way-labels))
          (setf level-labels (reverse level-labels))
          (mapcar #'reverse level-labels))
    (setf levlabs (list (first level-labels)))
    (setf waylabs (list (first way-labels)))
    (setf cells (combine cells))
    (cond
      (side-by-side 
       (when (> nways 1)
             (setf levels (prod levels))
             (setf side-by-side-labels 
                   (send self :side-by-side-labels 
                         nways levlabs level-labels waylabs way-labels))
             (setf levlabs (first side-by-side-labels))
             (setf waylabs (second side-by-side-labels))
             ))
      (t
       (when (= nways 2)
             
             (setf result 
                   (send self :make-stack 
                         levels cells colors way-labels level-labels))
             (setf mosaic-data (first result))
             (setf mosaic-levels (second result))
             (when (not array) (setf colors (third result)));PV was (setf colors (third result))
             ;starts PV
             (when array
                   (setf dim-bar-mat (mapcar 'length level-labels))
                   (setf raw-num-levels (reverse (array-dimensions array)))
                   (setf mat (apply 'bind-columns
                                    (mapcar #'(lambda (m) (make-array (list (second raw-num-levels) (first raw-num-levels))
                                                                      :initial-contents m))
                                            (split-list colors (* (first raw-num-levels) (second raw-num-levels))))))
                   (setf colors
                         (combine
                          (bind-rows 
                                 (repeat '0 (array-dimension mat '1))
                                 mat
                                )))
                   
                    )
                   ;PV corrects a bug when the number of ways is 3
             
             (setf waylabs (fourth result))
             (setf levlabs (fifth result))
             )))
    (when (or side-by-side (= nways 1))
          (setf invisible (- (max cells) cells))
          (setf mosaic-data(combine invisible cells))
          (setf mosaic-levels (combine 2 levels))
          (setf colors (combine (repeat 0 levels)
                (if colors colors (repeat -2.5 levels))))
          (setf levlabs (list (list "" "") (first levlabs) ))
          (setf waylabs (combine (if (send self :prob)
                                     "Probability" "Frequency") waylabs))
      )
    (list mosaic-data mosaic-levels colors waylabs levlabs)
    ))
  
(defmeth  stacked-bar-graph-proto  :switch-plot-type ()
  (let ((sbs (send self :side-by-side))
        (leg (send self :legend2))
        (overlays (send self :slot-value 'overlays)))
    (when overlays
          (if (send self :side-by-side)
              (send (first overlays) :install-button ':new-y)
              (send (first overlays) :remove-button ':new-y)))
    (when (or (equal leg "Stacked Bar Graph") (equal leg "Bar Graph"))
          (if sbs (send self :legend2 "Bar Graph")
              (send self :legend2 "Stacked Bar Graph")))))

(defmeth stacked-bar-graph-proto :make-stack 
            (levels cells colors way-labels level-labels)
  (let* ((matrix (matrix levels cells))
         (color-matrix)
         (nobs (first levels))
         (nvar (second levels))
         (col-sums (mapcar #'sum (column-list matrix)))
         (invisible (- (max col-sums) col-sums))
         (mosaic-data (combine (bind-rows invisible matrix)))
         (mosaic-levels (+ levels (list 1 0)))
         (waylabs way-labels)
         (levlabs (list (combine "" (first level-labels)) 
                        (second level-labels))))
    (if colors
        (setf color-matrix (transpose (matrix (reverse levels) colors)))
        (setf color-matrix (transpose (matrix (reverse levels) 
                    (repeat (* -2.5 (- (* 2 (mod (iseq nobs) 2)) 1)) nvar)))))
    (setf colors (combine (bind-rows (repeat 0 nvar) color-matrix)))
    (list mosaic-data mosaic-levels colors waylabs levlabs)))

(defmeth stacked-bar-graph-proto :side-by-side-labels 
  (nways levlabs level-labels waylabs way-labels)
  (dotimes (i (1- nways))
           (setf levlabs 
                 (list 
                  (combine 
                   (mapcar #'(lambda (L1)
                               (mapcar #' (lambda (L2)
                                            (strcat L1 "*" L2))
                                       (select level-labels (1+ i))))
                           (first levlabs)))))
           (setf waylabs (list (strcat (first waylabs) "*" 
                                       (select way-labels (1+ i))))))
  (list levlabs waylabs))

(defmeth stacked-bar-graph-proto :new-x ()
  (send self :side-by-side (not (send self :side-by-side)))
  (send self :switch-plot-type)
  (send self :new-plot
         (send self :bar-cells)
         (send self :bar-levels)
         :freq (send self :freq)
         :color-values (send self :bar-colors)
         :side-by-side (send self :side-by-side) 
         :way-labels (send self :bar-way-labels)
         :level-labels (send self :bar-level-labels))
  "newoverlay")

(defmeth stacked-bar-graph-proto :new-y ()
  (send self :prob (not (send self :prob)))
  (when (send self :side-by-side)
        (send self :start-buffering)
        (send self :draw-f-axis-labels)
        (send self :way-labels 
              (list (first (send self :way-labels))
                    (if (send self :prob) "Probability" "Frequency")))
        (send self :redraw)
        (send self :buffer-to-screen)
        ))

(defmeth stacked-bar-graph-proto :draw-f-axis-labels ()
  (let* ((maxf (max (send self :bar-cells)))
         (L (if (<= maxf 5) maxf 5))
         (M (if (<= maxf 5) L (1+ L)))
         (range (get-nice-range 0 maxf L));4
         (real-y-ticks (* (round (/ 100 L)) (iseq (1+ L))
                          (/ (second range) maxf)));25 4
         (canvas-y-ticks  
          (mapcar #'(lambda (y) (send self :real-to-canvas 0 y))
                  real-y-ticks))
         (length-y-ticks (- (select (select canvas-y-ticks 0) 1) 
                            (select (select canvas-y-ticks (1- L)) 1)))
         (canvas-y-ticks
          (mapcar #'(lambda (xy) 
                      (list (first xy)
                            (round (* (second xy) (/ (- length-y-ticks 5) length-y-ticks)))))
                  canvas-y-ticks))
         (y-values (select (rseq 0 (second range) (1+ L)) 
                           (iseq (1+ L))));5 4
         )
    (when (send self :prob) 
          (setf y-values (/ y-values (sum (send self :bar-cells)))))
    (when (= maxf (second range)) (setf L (1+ L)))
    (dotimes (i L);5
             (send self :draw-line 
                   (- (first (select canvas-y-ticks i)) 5)
                   (second (select canvas-y-ticks i))
                   (- (first (select canvas-y-ticks i)) 10)
                   (second (select canvas-y-ticks i)))
             (send self :draw-text-up
                   (if (send self :prob)
                       (format nil "~3,2f" (select y-values i))
                       (format nil "~d" (floor (select y-values i))))
                   (- (first (select canvas-y-ticks i)) 13)
                   (second (select canvas-y-ticks i))
                   1 0))))

(defmeth stacked-bar-graph-proto :show-rect-label (i x y show)
  (let ((dc (send self :draw-color))
        (bc (send self :back-color))
        (ch (send self :canvas-height))
        (cw (send self :canvas-width))
        (hth (ceiling (- (/ (+ (send self :text-ascent) 
                               (send self :text-descent)) 2) 1)))
        (cellnums (send self :cells))
        (colors (send self :color-values))
        (prob (send self :prob))
        (str) (strw) (diff)
        )
    (when prob
          (setf cellnums (/ cellnums (sum (send self :bar-cells)))))
    (send self :draw-mode 'xor)
    (when (send self :showing-labels)
          (setf str (select (send self :point-labels) i))
          (setf strw (send self :text-width str))
          (setf diff (- (- x (ceiling (/ strw 2))) (first (send self :content-rect)) 4))
          (when (> diff 0) (setf diff 0)) 
          (send self :draw-text str (- x diff) (+ hth y) 1 0))
    (send self :draw-text 
          (format nil (if prob '"p=~3,2f" '"f=~a") 
                  (select cellnums i)) 3 (- ch 6) 0 0)
    (if (send self :bar) 
        (when (send self :color-key?)
              (send self :draw-text
                    (format nil "c=~4,1f" (select colors i)) (- cw 3) (- ch hth) 2 0))
        (when (send self :shading) 
              (send self :draw-text
                    (format nil "c=~4,1f" (select colors i)) (- cw 3) (- ch hth) 2 0)))
    (send self :draw-mode 'normal)
    (send self :back-color bc)
    (send self :draw-color dc)))

(defmeth stacked-bar-graph-proto :draw-y-axis-labels (tw cr size)
"Args: TW CR SIZE
Makes tick marks and labels axes with way and level labels for each way."
  (cond
    ((not (send self :side-by-side)) (call-next-method tw cr size))
    (t
     (when (not (send self :setting-margins))
           (let* ((labels (send self :way-labels))
                  (nlabels (length labels))
                  (level-labels (send self :level-labels)) 
                  (level-label)
                  (lh (+ (send self :text-ascent) (send self :text-descent) 2))
                  (margin (send self :margin))
                  (n-each-level (mapcar #'length level-labels))
                  (first-text-col (- (first cr) tw))
                  (second-text-col (- first-text-col tw))
                  (third-text-col (- second-text-col tw))
                  (ycenter (+ (second cr) (floor (/ (fourth cr) 2))))
                  (mx (send self :draw-mx))
                  (rect-center-xy (send self :rect-centers))
                  (xs) (ys) (nycenters 0) (leftcenters)
                  (min-separation) (min-separation-needed) (xok) (ntextlines)
                  (x-tick-mark-labels)
                  (dtl t);dynamic tick labels
                  )
;Y-AXIS (if there is one)
    (when (> nlabels 1) 
;tickmarks
          (setf ys (first (column-list mx)))
          (setf nycenters (if (> nlabels 3) 
                              (* (second n-each-level) (fourth n-each-level))
                              (second n-each-level)))
          (setf leftcenters (send self :find-edges 
                                  ys rect-center-xy (min ys) 1 nycenters))
;tickmark labels
          (cond
            ((< nlabels 4)(setf y-tick-mark-labels (select level-labels 1)))
            ((> nlabels 3)
             (setf y-tick-mark-labels
                   (combine
                    (mapcar #'(lambda (i)
                                (repeat (select (select level-labels 1) i) 
                                        (select n-each-level 3)))
                            (iseq (select n-each-level 1)))))
             (setf y-tick-mark-labels 
                   (list y-tick-mark-labels
                         (repeat (select level-labels 3) 
                                 (length (select level-labels 1)))))
             (setf y-tick-mark-labels
                   (mapcar (lambda (l1 l2) (strcat l1 "*" l2))
                           (first y-tick-mark-labels) (second y-tick-mark-labels)))))          
;determine if tickmark labels would overlap    
          (setf tws (mapcar #'(lambda (L) (send self :text-width L))
                            y-tick-mark-labels))
          (setf min-separation-needed
                (max (mapcar #'(lambda (a b) (/ (+ a b) 2)) 
                             (select tws (iseq (1- nycenters))) 
                             (select tws (iseq 1 (1- nycenters))) )))
          (setf min-separation (min (difference leftcenters)))
          (setf yok (< min-separation-needed min-separation))          
;draw labels if won't overlap
          (send self :y-tick-mark-locs (list leftcenters first-text-col second-text-col))            
;axis label
          (when (send self :side-by-side)
                (send self :draw-text-up
                      (if (> nlabels 3)
                          (strcat (select labels 1) "*" (select labels 3))
                          (select labels 1))
                      second-text-col ycenter 1 0)))
    (when (not (send self :tick-mark-labels))
          (send self :tick-mark-labels 
                (if (> nlabels 1)
                    (list x-tick-mark-labels y-tick-mark-labels)
                    (list x-tick-mark-labels))))
    (send self :tick-marks-showing (list xok yok))
    (when (> (max (send self :bar-cells)) 1)
          (send self :draw-f-axis-labels))
    )))))
 

(defmeth stacked-bar-graph-proto :plot-help (&key (flush t)) 
  (let ((overlay (first (send self :slot-value (quote overlays))))
        (w))
    (setf w (plot-help-window (strcat "Help for Bar Graphs") :flush flush))
    (paste-plot-help (format nil  "BAR GRAPHS (AND MOSAIC PLOTS)~2%A Bar Graph is used to portray the (grouped) frequency distribution of a variable at the Nominal level of measurement. Such variables are called Category Variables in ViSta. It consists of vertical bars drawn above categories such that~%1.The height of the bar corresponds to the frequency ~%2.The bars are separated by empty space since the nominal level of measurement has separate, discrete categories.~2%") w)
(paste-plot-help (format nil "Stacked (Segmented) Bar Graphs~2%While a bar graph represents the frequencies of categories of one variable, a stacked (segmented) bar graph represents the frequencies of combinations of categories of two variables. In a stacked (or segmented) bar graph: ~%1.The horizontal axis still represents one variable, with each bar representing one of the catgories of the variable. ~%2.Each bar is segmented according to the categories of the second variable. Alternatively, each bar can be seen as being made up of smaller bars stacked on top of each other. ~2%") w)

    (paste-plot-help (format nil  "Comparison of Bar Graphs and Mosaic Plots~%A stacked bar-graph presents the same information as is presented by a mosaic plot: The frequencies of combinations of categories of two variables.~%1.A mosaic plot consists of rectangles laid out in a mosaic. The rectangles are like the sub-bars in a stacked bar-graph.~%2.In a mosaic plot, each column of rectangles represents a category of the variable on the horizontal axis.~%3.In a stacked bar-graph, each bar represents the overall frequency of a category of the variable plotted on the horizontal axis. In a mosaic, the several column of tiles are all the same height, representing 100%. Thus each tile in a mosaic represents a proportional frequency of a category combination.~%4.Whereas a stacked bar-graph's sub-bars representing the joint frequency of a category of each of the two variables, in a mosaic plot each rectangle represents the joint probability of a category of each of the two variables.") w)
(show-plot-help)))